/**
 * @file web存储事件相关
 * @author its-wild(https://gitee.com/its-wild)
 * @date 2022/07/05
 */

interface IListeners {
  [props: string]: Array<(newValue: any, oldValue: any, url: string) => void>
}

// 监听的事件
const listeners: IListeners = {}

/**
 * 事件类
 */
export class WebStorageEvent {
  /**
   * 添加对某个key的存储监听
   * @param {string} name 监听的key
   * @param {Function} callback 存储值发生变化时的回调方法
   */
  static on(name: keyof typeof listeners, callback: (newValue: any, oldValue: any, url: string) => void) {
    if (typeof listeners[name] === 'undefined') {
      listeners[name] = []
    }
    listeners[name].push(callback)
  }

  /**
   * 移除对某个key的存储监听
   * @param {string} name 监听的key
   * @param {Function} callback 存储值发生变化时的回调方法
   */
  static off(name: keyof typeof listeners, callback: (newValue: any, oldValue: any, url: string) => void) {
    // 如果存在监听就移除
    if (listeners[name]?.length) {
      listeners[name].splice(listeners[name].indexOf(callback), 1)
    }
    // 如果移除后是一个空数据就把这个空数组删除了
    if (listeners[name] && !listeners[name]?.length) {
      delete listeners[name]
    }
  }
  
  /**
   * 触发监听事件
   * @param {StorageEvent} e web存储事件源
   */
  static emit(e?: StorageEvent): void {
    if (typeof e === 'undefined' || typeof e.key === 'undefined') return

    const getValue = (data: string) => {
      try {
        return JSON.parse(data).value
      } catch (err) {
        return data
      }
    }

    const fire = (listener: (newValue: any, oldValue: any, url: string) => void) => {
      const newValue = getValue(e.newValue!)
      const oldValue = getValue(e.oldValue!)

      listener(newValue, oldValue, e.url)
    }

    if (typeof e === 'undefined' || typeof e.key === 'undefined') return

    const all = listeners[e.key!]

    if (typeof all !== 'undefined') {
      all.forEach(fire)
    }
  }
}
